import Module from "./Module"
import Logger from "../utils/Logger"

import UserData from "../data/UserData"
import { InviteUsersCommand, UserMentionSearchCommand, ResolveUserMentionsCommand } from "../command/user.command"
import userEnum from "../enum/user.enum"
import modelAccessEnum from "../enum/modelAccess.enum"

const g = new Logger("users-module")
export default class Users extends Module {
  store: any
  onUserMentionSearch: any
  userData: any
  resolveUserMentions: any
  inviteUsers: any
  config: { baseUrl: any; modelId: any; queue: any }
  constructor() {
    super(...arguments),
      (this.name = "users-module"),
      (this.store = null),
      (this.onUserMentionSearch = async e => {
        if (!this.store) return void g.error("No MDS user store")
        const t = await this.store.search(e.search)
        this.userData.loadKnownUsers(t)
      }),
      (this.resolveUserMentions = async e => {
        if (0 === e.userMentions.length) return void g.debug("No user mentions to resolve")
        const t = []
        if (
          (e.userMentions.forEach(e => {
            ;(this.userData.getUserInfoByEmail(e.email) && e.userStatus !== userEnum.MENTIONED) || t.push(e)
          }),
          t.length > 0)
        ) {
          const e = t.map(e => e.email)
          return this.searchUsers(new Set(e), userEnum.MENTIONED)
        }
      }),
      (this.inviteUsers = async e => {
        const { emails: t, modelAccess: i, message: n, noteId: s } = e
        if (0 === t.length) return
        const { baseUrl: r, modelId: o, queue: a } = this.config,
          l = `${r}/api/v2/shares/`,
          c = {
            object_type: "model",
            object_id: o,
            role: i,
            inviter_message: n,
            note: s
          },
          h = new Set()
        return (
          await Promise.all(
            e.emails.map(e =>
              a
                .post(l, {
                  responseType: "json",
                  body: Object.assign(Object.assign({}, c), {
                    email: e
                  })
                })
                .then(e => {
                  const t = e.user
                  this.userData.loadKnownUser({
                    id: t.sid,
                    email: t.email,
                    firstName: t.first_name,
                    lastName: t.last_name,
                    modelAccess: e.role
                  })
                })
                .catch(() => {
                  g.debug(`User Invite failed: ${e}`), h.add(e)
                })
            )
          ),
          h.size > 0 ? this.searchUsers(h, userEnum.FAILED) : void 0
        )
      })
  }
  async init(e, t) {
    this.config = e
    const i = e.api.user
    let n = modelAccessEnum.PUBLIC,
      s = [],
      r = !1

    ;(this.userData = new UserData(
      {
        id: i.id,
        firstName: i.firstName,
        lastName: i.lastName,
        email: i.email,
        modelAccess: n
      },
      i.loggedIn,
      r,
      s
    )),
      this.bindings.push(
        t.commandBinder.addBinding(UserMentionSearchCommand, this.onUserMentionSearch),
        t.commandBinder.addBinding(ResolveUserMentionsCommand, this.resolveUserMentions),
        t.commandBinder.addBinding(InviteUsersCommand, this.inviteUsers)
      ),
      t.market.register(this, UserData, this.userData)
  }
  async searchUsers(e, t) {
    if (!this.store) return
    const i = Array.from(e),
      n = await this.store.search(void 0, i)
    this.userData.loadSearchResults(n, i, t)
  }
  isPolicyFlagEnabled(e) {
    return this.userData.isPolicyFlagEnabled(e)
  }
}
